/** 
  -- The Performance Driven Lime Project -- 

  A self adaptive tuple space for mobile agents and hosts by dynamic
  adapting tuple's replication policy.
  
  Copyright (C) 2008
  Xing Jiankuan, Pan Wenhui
  SAGroup of Tsinghua University

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received this copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 */

package sagroup.pdlime;

import lights.interfaces.ITuple;
import lime2.LimeTuple;
import lime2.LimeTupleSpace;
import lime2.LimeWrapper;
import lime2.Location;
import lime2.TupleID;

/**
 * TVRLimeTuples contain data to application programmers. They are the <i>output</i>
 * of the in, read, etc.. methods of VersionedLimeTupleSpace. Programmers cannot
 * create new VersionedLimeTuples: they can extract all the internal information
 * from the ones returned by the VersionedLime system (TupleID included).
 * Because Lime communication can not see the VersionedLimeTuples, so the class
 * need not implement <code>java.io.Serializable</code>.
 * 
 */
public class TVRLimeTuple extends TVRLimeWrapper {

	/**
	 * for serialization
	 */
	private static final long serialVersionUID = -14410715399108104L;

	/**
	 * Constructor method. In this method, LimeTuple related fields tid and curr
	 * are generated automatically.<br>
	 * The parameters that input should not be null. And Location should never
	 * be UNSPECIFIED. TVRLimeTuple needs concrete fields.
	 * 
	 * @author Xing Jiankuan
	 */
	public TVRLimeTuple(TupleType type, TupleID vid, Long ver, Location dest,
			Location masterCurr, Location masterDest, Boolean isReplica,
			ITuple tuple) {

		this(LimeTupleSpace.nextTID(), Location.HERE, dest, type, vid, ver,
				masterCurr, masterDest, isReplica, tuple);
	}

	/**
	 * Constructor method. The parameters that input should not be null. And
	 * Location should never be UNSPECIFIED. TVRLimeTuple needs concrete fields.
	 * 
	 * @author Xing Jiankuan
	 */
	public TVRLimeTuple(TupleID tid, Location curr, Location dest,
			TupleType type, TupleID vid, Long ver, Location masterCurr,
			Location masterDest, Boolean isReplica, ITuple tuple) {

		super(tid, curr, dest, type, vid, ver, masterCurr, masterDest,
				isReplica, tuple);
		if (tid == null || curr == null || curr == Location.UNSPECIFIED
				|| dest == null || dest == Location.UNSPECIFIED || type == null
				|| ver == null || masterCurr == null
				|| masterCurr == Location.UNSPECIFIED || masterDest == null
				|| masterDest == Location.UNSPECIFIED || isReplica == null
				|| tuple == null) {
			throw new IllegalArgumentException(
					"In TVRLimeTuple, concrete fields are must");
		}
	}

	public TVRLimeTuple(LimeTuple limeTuple) {
		super(limeTuple);
		this.limeWrapper.id = LimeTupleSpace.nextTID();
	}
	/**
	 * Construct a TVRLimeTuple from a flattened tuple. This ITuple must contain
	 * TVRLimeTuple fields or LimeTuple fields. You should never use a tuple that
	 * contains only user data to invoke this constructor.
	 * @param tuple
	 */
	public TVRLimeTuple(ITuple tuple) {
		super(tuple);
		this.limeWrapper.id = LimeTupleSpace.nextTID();
	}

	public ITuple toFlatTuple() {
		return super.flattenTVRLimeWrapper(TVR_FIELDS);
	}

	/**
	 * facility to create a master TVRLimeTuple instance
	 * 
	 * @param type
	 *            tuple's type
	 * @param dest
	 *            destination
	 * @param t
	 *            user data type
	 * @return result TVRLimeTuple
	 * @author Xing Jiankuan
	 */
	public static TVRLimeTuple createMaster(TupleType type, Location dest,
			ITuple t) {

		return new TVRLimeTuple(LimeTupleSpace.nextTID(), Location.HERE, dest,
				type, TVRLimeTupleSpace.nextVID(), new Long(
						TVRLimeConstants.INITIAL_VER_NUM), Location.HERE, dest,
				new Boolean(false), t);
	}

	public static TVRLimeTuple replicate(TVRLimeTuple tlt) {
		// TODO:facility to replicate a TVRLimeTuple
		return null;
	}

	/**
	 * toString method.
	 * 
	 * @return concise textual representation of this LimeTuple
	 */
	public String toString() {
		return "[TVRLimeTuple] " + super.toString();
	}

	/**
	 * Create current TVRLimeTuple from a LimeTuple instance
	 * 
	 * @Requires: nothing
	 * @Modifies: nothing
	 * @Effects: If the tuple in lt is a valid TVR Lime tuple, then current
	 *           TVRLimeTuple is filled. <br>
	 *           Else an IllegalArgumentException is thrown
	 * 
	 * @param lt
	 */
	public void createFromLimeTuple(LimeTuple lt) {
		this.createFromLimeWrapper(lt);
	}

	/**
	 * Convert current TVRLimeTuple instance to LimeTuple. All TVR related
	 * fields are flattened, and put into the result.
	 * 
	 * @return a lime tuple instance
	 * @author Xing Jiankuan
	 */
	public LimeTuple toLimeTuple() {
		ITuple t = this.flattenTVRLimeWrapper(TVR_FIELDS);
		return new LimeTuple(limeWrapper.id, limeWrapper.cur, limeWrapper.dest,
				t);
	}

	/**
	 * Judge whether current TVRLimeTuple instance is older than the input one.
	 * That is, take the comparison between them.
	 * 
	 * @param tlt
	 *            another TVRLimeTuple instance
	 * @return true if current instance is older, false otherwise.
	 * @author Xing Jiankuan
	 */
	public boolean isOlderThan(TVRLimeTuple tlt) {
		return ver.longValue() < tlt.ver.longValue();
	}

	public LimeTuple getLimeTuple() {
		LimeWrapper wrapper = limeWrapper;
		return new LimeTuple(wrapper.id, wrapper.cur, wrapper.dest,
				wrapper.tuple);
	}

}
